<template>
  <div class="v-upload">
    <el-upload multiple :headers="headers" :action="uploadFileUrl" :before-upload="handleBeforeUpload"
      :limit="props.limit" :on-error="handleUploadError" :on-exceed="handleExceed" :on-success="handleUploadSuccess"
      :show-file-list="false" v-bind="$attrs" :class="props.classes">
      <slot />
    </el-upload>
    <el-progress v-if="props.progress && progressPercent" :percentage="progressPercent" :width="128" />
  </div>
</template>

<script setup>
import { getToken } from "@/utils/auth";
import { ElMessage } from 'element-plus'


const props = defineProps({
  type: { type: String, default: 'img' }, // 上传类型
  limit: { type: Number, default: 1 },
  classes: { type: String, default: '' }, // el-upload的class
  validator: { type: Function, default: () => { } }, // 校验函数
  progress: Boolean // 是否使用进度条
})
const emit = defineEmits(['success', 'error'])
const key = ref(0)
const number = ref(0);
const fileList = ref([]);
const uploadList = ref([]);

const progressPercent = ref(0)
watch(progressPercent, (val) => {
  if (val === 100) {
    const timer = setTimeout(() => {
      progressPercent.value = 0
      clearTimeout(timer)
    }, 1000)
  }
})
watch(() => props.modelValue, val => {
  if (val) {
    let temp = 1;
    // 首先将值转为数组
    const list = Array.isArray(val) ? val : props.modelValue.split(',');
    // 然后将数组转为对象数组
    fileList.value = list.map(item => {
      if (typeof item === "string") {
        item = { name: item, url: item };
      }
      item.uid = item.uid || new Date().getTime() + temp++;
      return item;
    });
  } else {
    fileList.value = [];
    return [];
  }
}, { deep: true, immediate: true });


const uploadFileUrl = ref(''); // 上传文件服务器地址
const headers = ref({ Authorization: "Bearer " + getToken() });

onMounted(() => {
  uploadFileUrl.value = props.type == 'img' ? import.meta.env.VITE_APP_BASE_API + "/base/upload" : import.meta.env.VITE_APP_BASE_API + "/base/upload-file"
})


const handleBeforeUpload = (file) => {

  // 校检文件类型
  // if (props.fileType.length) {
  //   const fileName = file.name.split('.');
  //   const fileExt = fileName[fileName.length - 1];
  //   const isTypeOk = props.fileType.indexOf(fileExt) >= 0;
  //   if (!isTypeOk) {
  //     ElMessage(`文件格式不正确, 请上传${props.fileType.join("/")}格式文件!`);
  //     return false;
  //   }
  // }
  // 校检文件大小
  if (props.fileSize) {
    const isLt = file.size / 1024 / 1024 < props.fileSize;
    if (!isLt) {
      ElMessage.error(`上传文件大小不能超过 ${props.fileSize} MB!`);
      return false;
    }
  }
  number.value++;
  return true;
}

// 上传失败
const handleUploadError = (err) => {
  ElMessage.error("上传文件失败");
}

// 文件个数超出
const handleExceed = () => {
  ElMessage.error(`上传文件数量不能超过 ${props.limit} 个!`);
}

// 上传成功回调
const handleUploadSuccess = (res, file) => {
  ElMessage.warning("完成");

  if (res.code === 200) {
    uploadList.value.push({ name: res.data['filename'], url: res.data['data-show-file'] });
    uploadedSuccessfully();
  } else {
    number.value--;
    proxy.$modal.closeLoading();
    proxy.$modal.msgError(res.msg);
    proxy.$refs.fileUpload.handleRemove(file);
    uploadedSuccessfully();
  }
}

// 上传结束处理
const uploadedSuccessfully = () => {
  if (number.value > 0 && uploadList.value.length === number.value) {
    fileList.value = fileList.value.filter(f => f.url !== undefined).concat(uploadList.value);
    uploadList.value = [];
    number.value = 0;
    ElMessage.success("上传成功");
    // const list = fileList.value.map(i => i.url)
    emit("success", fileList.value);
  }
}

const beforeUpload = (file) => {
  if (props.limit === 1) key.value++
  return new Promise((resolve, reject) => {
    const { name, type, size } = file
    const url = URL.createObjectURL(file)
    const types = {
      // 图片上传
      img: () => {
        let img = document.createElement('img')
        img.src = url
        img.onload = () => {
          const { width, height } = img
          const fileInfo = { width, height, size, name, type }
          // 校验
          const massge = props.validator && props.validator(fileInfo)
          img = null
          massge && reject(massge)
          resolve(fileInfo)
        }
      },
      // 视频上传
      video: () => {
        let video = document.createElement('video')
        video.preload = 'metadata'
        video.src = url
        video.autoplay = true
        video.onloadedmetadata = () => {
          const { duration, videoWidth: width, videoHeight: height } = video
          const fileInfo = { width, height, size, name, type, time: Math.ceil(duration) }
          // 校验
          const massge = props.validator && props.validator(fileInfo)
          video = null
          massge && reject(massge)
          resolve(fileInfo)
        }
      },
      // 文件上传
      file: () => {
        resolve()
      }
    }
    types[props.type]()
  })
}
const httpRequest = (fileData) => {
  const { file } = fileData
  beforeUpload(file).then(fileInfo => {
    progressPercent.value = 0
    let formData = new FormData();
    formData.append('file', file)
    api[props.type === 'img' ? 'uploadImg' : 'uploadFile'](formData).then(res => {
      const spark = new MD5.ArrayBuffer()
      spark.append(file)
      const secret = spark.end(false)
      emit('success', { ...fileInfo, ...res.data, secret })
    })
  }).catch(e => {
    emit('error', e)
  })
}
</script>

<style lang="scss" scoped></style>